package mcom.xmks.bluetooth.mesh;

import static cn.wch.meshlib.frame.ack.AckType.PROVISION_INFO;
import static cn.wch.meshlib.frame.ack.AckType.QUERY_STATE;

import android.app.Activity;
import android.app.Dialog;
import android.content.Intent;
import android.os.Bundle;
import android.view.Gravity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.FrameLayout;

import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.google.android.material.bottomnavigation.BottomNavigationView;
import com.google.android.material.navigation.NavigationBarView;

import java.util.List;

import cn.wch.meshlib.core.MeshServer;
import cn.wch.meshlib.frame.ack.AckFrame;
import cn.wch.meshlib.frame.ack.AckType;
import io.reactivex.Emitter;
import mcom.xmks.bluetooth.mesh.adapter.GroupListAdapter;
import mcom.xmks.bluetooth.mesh.adapter.NodeListAdapter;
import mcom.xmks.bluetooth.mesh.base.NodeMainActivity;
import mcom.xmks.bluetooth.mesh.constant.IntentConstant;
import mcom.xmks.bluetooth.mesh.core.CustomEvent;
import mcom.xmks.bluetooth.mesh.core.DataModel;
import mcom.xmks.bluetooth.mesh.core.NodeViewModel;
import mcom.xmks.bluetooth.mesh.dialog.DialogUtil;
import mcom.xmks.bluetooth.mesh.dialog.InputGroupInfoDialog;
import mcom.xmks.bluetooth.mesh.storage.GroupStorageUtil;
import mcom.xmks.bluetooth.mesh.storage.NodeItem;
import mcom.xmks.bluetooth.mesh.storage.StorageUtil;
import mcom.xmks.bluetooth.mesh.utils.ConvertUtil;
import mcom.xmks.bluetooth.mesh.utils.LogTool;

public class MainActivity extends NodeMainActivity implements View.OnClickListener {
    private NodeListAdapter nodeListAdapter;
    private GroupListAdapter groupListAdapter;
    private NodeViewModel viewModelProvider=null;
    private boolean networkPageFlag=true;
    //private boolean isConnected=false;
    private RecyclerView list_node,list_group;
    // private MenuItem menu_connect,menu_disconnect,menu_refreshState;
    private BottomNavigationView nav_view;
    private FrameLayout frame_node,frame_group;

    private ActivityResultLauncher<Intent> activityResult  = registerForActivityResult(
            new ActivityResultContracts.StartActivityForResult(),
            result -> {
                if(result.getData()!=null){
                    if (result.getData().hasExtra(IntentConstant.SCAN_SELECT_DEVICE)) {
                        String stringExtra = result.getData().getStringExtra(IntentConstant.SCAN_SELECT_DEVICE);
                        LogTool.d("activity result data:" + stringExtra);
                        handleMACAddress(stringExtra);
                    }else if (result.getData().hasExtra(IntentConstant.REFRESH_LIST)) {
                        boolean rfresh=result.getData().getBooleanExtra(IntentConstant.REFRESH_LIST,false);
                        if(rfresh) {  //刷新注册的设备列表
                            setNodeList();
                            setGroupList();
                        }
                    }
                }
            });
    @Override
    protected void setView() {
        setContentView(R.layout.activity_main);
        nav_view=this.findViewById(R.id.nav_view);
        frame_node=this.findViewById(R.id.frame_node);
        frame_group=this.findViewById(R.id.frame_group);
        list_node=this.findViewById(R.id.list_node);
        list_group=this.findViewById(R.id.list_group);
        registerBluetoothStateReceiver();
    }
    @Override
    protected void initWidget() {
        nav_view.setSelectedItemId(R.id.navigation_network);
        nav_view.setOnItemSelectedListener(itemSelectedListener);
        this.findViewById(R.id.linear_node).setOnClickListener(this);
        this.findViewById(R.id.linear_group).setOnClickListener(this);
        this.openBluetooth();
        MeshServer.getInstance().setWatchAckListener(frame -> {
            switch (frame.getAckType()){
                case AckType.DELETE_INFO:
                    showToast("已经删除节点"+ ConvertUtil.getNodeHexString(frame.getNetAddress())+"的存储信息");
                    break;
                case AckType.TRANSFER:
                    showToast("已经向节点"+ConvertUtil.getNodeHexString(frame.getNetAddress())+"传输数据"+ConvertUtil.fromByteArray2HexString(frame.getData()));
                    break;
            }
        });
        viewModelProvider=new ViewModelProvider(this).get(NodeViewModel.class);
        setNodeList();
        setGroupList();
        viewModelProvider.event.observe(this, event -> {
            Bundle bundle;
            switch (event.getType()){
                case CustomEvent.EVENT_ADD_NODE: {
                    addNode();
                    break;
                }
                case CustomEvent.EVENT_TO_NODE_DETAIL: {
                    bundle = event.getBundle();
                    if (bundle != null) {
                        if (bundle.containsKey(IntentConstant.BUNDLE_NODE_NAME)) {
                            int nodeAddress = bundle.getInt(IntentConstant.BUNDLE_NODE_ADDRESS, -1);
                            String nodeName = bundle.getString(IntentConstant.BUNDLE_NODE_NAME);
                            toNodeDetail(nodeAddress, nodeName);
                        }
                    }
                    break;
                }
                case  CustomEvent.EVENT_TO_GROUP_DETAIL: {
                    bundle = event.getBundle();
                    if (bundle != null) {
                        if (bundle.containsKey(IntentConstant.BUNDLE_GROUP_NAME)) {
                            int groupAddress = bundle.getInt(IntentConstant.BUNDLE_GROUP_ADDRESS, -1);
                            String groupName = bundle.getString(IntentConstant.BUNDLE_GROUP_NAME);
                            toGroupDetail(groupAddress, groupName);
                        }
                    }
                    break;
                }
                case CustomEvent.EVENT_DELETRTE_NODE_LOCAL: {
                    bundle = event.getBundle();
                    if (bundle != null) {
                        int nodeAddress = bundle.getInt(IntentConstant.BUNDLE_NODE_ADDRESS, -1);
                        if (nodeAddress != -1) {
                            //delete local
                            deleteNode(nodeAddress);
                        }
                    }
                    break;
                }
            }
        });
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        LogTool.d("onNewIntent");
        setIntent(intent);//must store the new intent unless getIntent() will return the old one
        checkShareFile();
        if(viewModelProvider!=null)
            viewModelProvider.refreshAllNodeState();
    }
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_main,menu);
        menu.findItem(R.id.connect).setVisible(!isConnected);
        menu.findItem(R.id.disconnect).setVisible(isConnected);
        menu.findItem(R.id.refreshState).setVisible(isConnected && networkPageFlag);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
        switch (item.getItemId()){
            case R.id.refreshState:
                queryNodeState();
                break;
            case R.id.connect:
                connect();
                break;
            case R.id.disconnect:
                disconnectBLE(false);
                List<NodeItem>nodes= StorageUtil.getAllNode();
                for(NodeItem nodeItem:nodes) {
                    StorageUtil.updateNodeState(nodeItem.getNodeAddress(), false);
                }
                if(viewModelProvider!=null)
                    viewModelProvider.refreshAllNodeState();
                break;
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    protected void onBluetoothStateListener(boolean stateON, boolean isTurning) {
        super.onBluetoothStateListener(stateON, isTurning);
        showToast(String.valueOf(stateON));
    }
    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.linear_node:
                //addNode();
                viewModelProvider.addNode();
                break;
            case R.id.linear_group:
//                requestPermissions(Manifest.permission.ACCESS_COARSE_LOCATION,
//                        Manifest.permission.ACCESS_FINE_LOCATION,
//                        Manifest.permission.CAMERA);
                showCreateGroupDialog();
                break;
        }
    }
    NavigationBarView.OnItemSelectedListener itemSelectedListener=new NavigationBarView.OnItemSelectedListener() {
        @Override
        public boolean onNavigationItemSelected(@NonNull MenuItem item) {
            switch (item.getItemId()){
                case R.id.navigation_network:
                    frame_node.setVisibility(View.VISIBLE);
                    frame_group.setVisibility(View.GONE);
                    networkPageFlag=true;
                    invalidateOptionsMenu();
                    break;
                case R.id.navigation_group:
                    frame_node.setVisibility(View.GONE);
                    frame_group.setVisibility(View.VISIBLE);
                    networkPageFlag=false;
                    invalidateOptionsMenu();
                    break;
            }
            return true;
        }
    };
    private void connect(){
        toScanActivity(true);
    }
    private void addNode(){
        if(isConnected) {
            DialogUtil.getInstance().showSimpleDialog(this,
                    "增加节点操作需要先断开与当前蓝牙连接,是否断开?",
                    "断开", "取消",
                    new DialogUtil.IResult() {
                        @Override
                        public void onContinue() {
                            disconnectBLE(false);
                        }
                        @Override
                        public void onCancel() {
                        }
                    });
        }else{
            toScanActivity(false);
        }
    }

    /**
     * 到扫描活动页面
     * @param netConfigNet 非配置节点信息
     */
    private void toScanActivity(boolean netConfigNet){
        Intent intent=new Intent(this, ScanActivity.class);
        intent.putExtra(IntentConstant.SCAN_SOURCE_ACTIVITY,MainActivity.class.getName());
        if(netConfigNet){
            intent.putExtra(IntentConstant.SCAN_TARGET_ACTIVITY,MainActivity.class.getName());
            intent.putExtra(IntentConstant.SCAN_ONLY_CONFIGURED,true);
        }else{
            intent.putExtra(IntentConstant.SCAN_TARGET_ACTIVITY,ConfigNetActivity.class.getName());
            intent.putExtra(IntentConstant.SCAN_ONLY_CONFIGURED,false);
        }
        //startActivityForResult(intent,0);
        activityResult.launch(intent);
    }

    @Override
    protected void onConnectBLESuccess(String mac) {
        super.onConnectBLESuccess(mac);
        updateNetInformation();
    }
    private void handleMACAddress(String mac){
        if(mac!=null){
            connectBLE(mac);
        }else{
            LogTool.d("mac address is null,can not connect");
        }
    }
    private void queryNodeState(){
        List<NodeItem>nodes= StorageUtil.getAllNode();
        LogTool.d("queryNodeState");
        DataModel.getInstance().rxjavaExecuteAll(this, "正在查询节点状态", nodes, new Emitter<NodeItem>() {
            @Override
            public void onNext(NodeItem item) {
                try {
                    AckFrame frame=MeshServer.getInstance().queryNodeState(item.getNodeAddress());
                    if(frame.getAckType()==QUERY_STATE){
                        StorageUtil.updateNodeState(frame.getNetAddress(),frame.getStatusCode()==0);
                    }else{
                        showToast("error ack");
                    }
                } catch (Exception e) {
                    showToast(e.getMessage());
                }
            }

            @Override
            public void onError(Throwable e) {
                showToast(e.getMessage());
            }

            @Override
            public void onComplete() {
                if(viewModelProvider!=null)
                    viewModelProvider.refreshAllNodeState();
            }
        });
    }
    private void updateNetInformation(){
        LogTool.d("---updateNetInformation---");
        try {
            AckFrame ackFrame= MeshServer.getInstance().getNetworkInfo();
            if(ackFrame.getAckType()==PROVISION_INFO){
                showToast("更新网络信息"+(ackFrame.getStatusCode()==0?"成功" : "失败"));
                LogTool.d("updateNetInformation--->"+(ackFrame.getStatusCode()==0?"success" : "fail"));
                if(ackFrame.getStatusCode()==0){
                    LogTool.d("ivIndex:"+ ackFrame.getIvIndex()+" flag:"+ackFrame.getFlag());
                    StorageUtil.setIvIndex(ackFrame.getIvIndex());
                    StorageUtil.setFlag(Byte.toUnsignedInt(ackFrame.getFlag()));
                }
            }else{
                showToast("error ack");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 跳转到组详细信息
     * @param groupAddress 组地址
     * @param groupName 组名称
     */
    public void toGroupDetail(int groupAddress,String groupName){
        if(!isConnected){
            //showToast("请先连接设备")
            toScanActivity(true);
            return;
        }
        Intent intent = new Intent(this, GroupDetailActivity.class);
        intent.putExtra(IntentConstant.GROUP_NET_NAME,groupName);
        intent.putExtra(IntentConstant.GROUP_NET_ADDRESS,groupAddress);
        startActivity(intent);
    }

    /**
     * 跳转到节点详细信息
     * @param nodeAddress 节点地址
     * @param nodeName 节点名称
     */
    private void toNodeDetail(int nodeAddress,String nodeName){
        if(!isConnected){
            //showToast("请先连接设备")
            toScanActivity(true);
        }else {
            showSnackBar(this, () -> {
                Intent intent = new Intent(this, NodeDetailActivity.class);
                intent.putExtra(IntentConstant.NODE_NET_NAME, nodeName);
                intent.putExtra(IntentConstant.NODE_NET_ADDRESS, nodeAddress);
                //startActivity(intent);
                activityResult.launch(intent);
            }, () -> {
                Intent intent = new Intent(this, NodeOTAActivity.class);
                intent.putExtra(IntentConstant.NODE_NET_NAME, nodeName);
                intent.putExtra(IntentConstant.NODE_NET_ADDRESS, nodeAddress);
                startActivity(intent);
            });
        }
    }
    public void deleteNode(int nodeAddress){
        if(nodeAddress<0){
            LogTool.d("node address is null or negative");
        }else{
            DialogUtil.getInstance().showSimpleDialog(this,"确定从本地强制删除节点信息?",
                    "删除","取消", new DialogUtil.IResult() {
                @Override
                public void onContinue() {
                    StorageUtil.deleteNode(nodeAddress);
                    GroupStorageUtil.removeNodeFromAllGroups(nodeAddress);
                    if(viewModelProvider!=null) {
                        viewModelProvider.refreshAllNodeState();
                        viewModelProvider.refreshAllGroupState();
                    }
                }
                @Override
                public void onCancel() {
                }
            });
        }
    }
    private void showSnackBar(Activity activity, OnNodeConfig nodeConfig, OnNodeOTA nodeOTA){
        //1、使用Dialog、设置style
        Dialog dialog = new Dialog(activity, R.style.DialogTheme);
        //2、设置布局
        View view = View.inflate(activity, R.layout.item_snack, null);
        dialog.setContentView(view);
        Window window = dialog.getWindow();
        //设置弹出位置
        window.setGravity(Gravity.BOTTOM);
        //设置弹出动画
        window.setWindowAnimations(R.style.main_menu_animStyle);
        //设置对话框大小
        window.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        dialog.show();
        dialog.findViewById(R.id.tv_ble_config).setOnClickListener(v->{
            dialog.dismiss();
            nodeConfig.NodeConfig();
        });
        dialog.findViewById(R.id.tv_ble_ota).setOnClickListener(v->{
            dialog.dismiss();
            nodeOTA.nodeOTA();
        });
        dialog.findViewById(R.id.tv_cancel).setOnClickListener (v->{
            dialog.dismiss();
        });
    }
    private interface OnNodeConfig {
        void NodeConfig() ;
    }
    private interface OnNodeOTA{
        void nodeOTA();
    }
    private void setNodeList(){
        // NodeViewModel viewModel=  new ViewModelProvider(this).get(NodeViewModel.class);
        nodeListAdapter=new NodeListAdapter(new NodeListAdapter.OnClickListener() {
            @Override
            public void onClick(int netAddress, String name) {
                viewModelProvider.toNodeDetail(netAddress,name);
            }
            @Override
            public void onLongClick(int netAddress, String name) {
                viewModelProvider.forceDeleteNodeLocal(netAddress,name);
            }
        });
        list_node.setAdapter(nodeListAdapter);
        list_node.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
        list_node.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL));
        //订阅事件
        viewModelProvider.nodeList.observe(this, items -> {
            nodeListAdapter.loadAllNodes(items);
        });
        //获取节点列表
        viewModelProvider.refreshAllNodeState();
    }
    private void setGroupList(){
        groupListAdapter=new GroupListAdapter(new GroupListAdapter.OnClickListener() {
            @Override
            public void onClick(int groupAddress, String groupName) {
                viewModelProvider.toGroupDetail(groupAddress,groupName);
            }
            @Override
            public void onLongClick(int groupAddress, String groupName) {
            }
        });
        list_group.setAdapter(groupListAdapter);
        list_group.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
        list_group.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL));
        viewModelProvider.groupList.observe(this,items->{
            groupListAdapter.loadAllGroups(items);
        });
        viewModelProvider.refreshAllGroupState();
    }
    private void showCreateGroupDialog(){
        InputGroupInfoDialog dialog = new InputGroupInfoDialog();
        dialog.setCancelable(false);
        dialog.setCreateGroupListener((address, name) -> {
            LogTool.d("create group:0x"+Integer.toHexString(address)+name);
            viewModelProvider.addGroup(name,address);
        });
        dialog.show(getSupportFragmentManager(),InputGroupInfoDialog.class.getName());
    }
}